package com.nf.practice.downloadFile;

import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

// 多线程分批次下载
// 根据指定条件下载影像件
public class AccordingConditionDownloadImg6 {

    private static final int THREAD_POOL_SIZE = 15; // 线程池大小
    private static final int BUFFER_SIZE = 4096; // 缓冲区大小
    private static final int BATCH_SIZE = 200;

    // 1、根据单号下载影像件
    @Test
    public void accordingAppNoDownloadImg() {
        String preDic = "C:/file/";

        List<PicExportDetail> dataList = new ArrayList<>();

        String excelName = "E:/file/E类补充.xlsx";
//        String excelName = "E:/file/1228测试.xlsx";

        // 获取单号列表
        List<PicData> appNos = EasyExcel.read(excelName)
                .head(PicData.class)
                .sheet()
                .doReadSync();
        List<String> appNoList = appNos.stream().map(item -> item.getAppNo()).collect(Collectors.toList());


        int batchCount = 0; // 用于存储批次的计数器

        Long begin = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        List<Future<Boolean>> futures = new ArrayList<>();
        for (int i = 0; i < appNoList.size(); i += BATCH_SIZE) {
            batchCount++;
            int endIndex = Math.min(i + BATCH_SIZE, appNoList.size());
            List<String> batchNoList = appNoList.subList(i, endIndex);

            Callable<Boolean> task = new AccordingConditionDownloadImg6.DownloadTask(batchNoList, String.valueOf(batchCount), dataList);
            Future<Boolean> future = executorService.submit(task);
            futures.add(future);
        }

        // 等待所有批次任务完成
        for (Future<Boolean> item : futures) {
            try {
                item.get(); // 这会阻塞，直到该future完成
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        executorService.shutdown(); // 关闭线程池

        File directory = new File(preDic);
        // 如果目录不存在，则创建它
        if (!directory.exists()) {
            directory.mkdirs();
        }
        ExcelWriter writer = ExcelUtil.getWriter(new File(preDic + "E类补充.xlsx"));
        if(!CollectionUtils.isEmpty(dataList)){
            writer.setSheet(0).write(dataList);
            writer.flush();
        }
        System.out.println("下载结束,计算耗时：" + (System.currentTimeMillis() - begin) + "ms");

    }

    public static String doPost(String url, Object params) {
        String json = JSON.toJSONString(params);
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        String response = null;
        try {
            StringEntity s = new StringEntity(json);
            s.setContentEncoding("UTF-8");
            s.setContentType("application/json");//发送json数据需要设置contentType
            post.setEntity(s);
            HttpResponse res = client.execute(post);
            if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                response = EntityUtils.toString(res.getEntity());
            }
        } catch (Exception e) {
            e.printStackTrace();
//            throw new RuntimeException(e);
        }
        return response;
    }

    private static class DownloadTask implements Callable<Boolean> {
        private final String preDic = "C:/file/E类/";

//        private final List<String> idNoDirs = Arrays.asList("B","B01","B02");
//        private final List<String> loanContractDirs = Arrays.asList("A","AA05", "AB05", "AC02", "AE03", "AF01", "AG02", "AD02", "AH01", "AI02", "U04", "U11", "K");
//        private final List<String> guaranteeContractDirs = Arrays.asList("S", "S03", "AE04", "AA07", "U15");

        private final List<String> loanContractDirs = Arrays.asList("A");
        private final List<String> targetDir = Arrays.asList(
                "A"
        );

//        private final List<String> targetDir = Arrays.asList(
//                "AA05",
//                "AB05",
//                "AC02",
//                "AE03",
//                "AF01",
//                "AG02",
//                "AD02",
//                "AH01",
//                "AI02",
//                "U04",
//                "U11",
//                "K",
//                "B",
//                "B01",
//                "B02",
//                "S",
//                "S03",
//                "AE04",
//                "AA07",
//                "U15"
//        );

        private List<String> batchAppNoList;
        private String batchCount;
        private List<PicExportDetail> dataList;

        public DownloadTask(List<String> batchAppNoList, String batchCount, List<PicExportDetail> dataList) {
            this.batchAppNoList = batchAppNoList;
            this.batchCount = batchCount;
            this.dataList = dataList;
        }

        @Override
        public Boolean call() {
            // 影像件生产地址
            String picUrl = "http://192.168.40.78:8081";
//            String picUrl = "http://172.16.10.5:31312";

            for (String appNo : batchAppNoList) {
                int idNoNum = 0;
                int loanContractNum = 0;
                int guaranteeContractNum = 0;
                PicExportDetail data = new PicExportDetail();

                Map<String, Object> reqMap = new HashMap<>();
                reqMap.put("appNo", appNo);
                // 根据appNo调用影像件系统获取影像件存放地址和目录
                String resJson = doPost(picUrl + "/file-system/picture/queryImgListAll", reqMap);
                JSONObject jsonData = JSONObject.parseObject(resJson);
                JSONArray resArr = jsonData.getJSONArray("data");
                String status = jsonData.getString("status");
                if (!"S".equals(status) || CollectionUtils.isEmpty(resArr)) {
                    data.setAppNo(appNo)
                            .setIdNoNum(String.valueOf(idNoNum))
                            .setLoanContractNum(String.valueOf(loanContractNum))
                            .setGuaranteeContractNum(String.valueOf(guaranteeContractNum));
                    dataList.add(data);
                } else {
                    List<JSONObject> list = JSONObject.parseArray(jsonData.getJSONArray("data").toJSONString(), JSONObject.class);
                    try {
                        // 遍历影像件并根据目录存放对应的文件到本地
                        for (int i = 0; i < list.size(); i++) {
                            // 文件地址
                            String fileUrl = list.get(i).getString("filePath");
                            // String appNo = list.get(i).getString("appNo");
                            // 文件名
                            String fileName = list.get(i).getString("fileName");
                            // 文件目录
                            String subclassSort = list.get(i).getString("subclassSort");
                            if (!targetDir.contains(subclassSort)) {
                                continue;
                            }
                            // 目录中文名
//                    String chDir = dirsEngToCh.get(subclassSort);
                            // 创建目录
//                    String directoryPath = "E:/file/" + appNo + "/" + chDir + "/";

                            String directoryPath = preDic + appNo + "/";

                            File directory = new File(directoryPath);
                            // 如果目录不存在，则创建它
                            if (!directory.exists()) {
                                directory.mkdirs();
                            }
                            // 创建文件对象，使用fileName作为文件名
                            File file = new File(directory, fileName);
                            // 使用Hutool的HttpUtil工具类下载影像件文件,文件保存的关键步骤
                            HttpUtil.downloadFile(fileUrl, file);
                            System.out.println(appNo + "-" + "下载成功!");

//                            if (idNoDirs.contains(subclassSort)) {
//                                idNoNum++;
//                            } else if (loanContractDirs.contains(subclassSort)) {
//                                loanContractNum++;
//                            } else if (guaranteeContractDirs.contains(subclassSort)) {
//                                guaranteeContractNum++;
//                            }

                            if (loanContractDirs.contains(subclassSort)) {
                                loanContractNum++;
                            }

                        }

                        data.setAppNo(appNo)
                                .setIdNoNum(String.valueOf(idNoNum))
                                .setLoanContractNum(String.valueOf(loanContractNum))
                                .setGuaranteeContractNum(String.valueOf(guaranteeContractNum));
                        dataList.add(data);
                    } catch (Exception e) {
                        data.setAppNo(appNo)
                                .setIdNoNum(String.valueOf(idNoNum))
                                .setLoanContractNum(String.valueOf(loanContractNum))
                                .setGuaranteeContractNum(String.valueOf(guaranteeContractNum));
                        dataList.add(data);
                        System.out.println(appNo + "-" + "下载异常!" + e.getMessage());
                    }
                }
            }
            return true;
        }
    }

}
